#include <linux/types.h>
#include <linux/ioport.h>
#include <asm/io.h>
/**
 * Pins :
 * 	1 = data bit 1
 * 	2 = data bit 2
 *	3 = data bit 3 (if !useCustomData) / customData bit (if useCustomData)
 *  	4 = writeStatus
 *	5 = readStatus
 */

typedef unsigned char byte;
typedef struct {
	byte data;
	byte customData;
	int useCustomData;
	int writeStatus;
	int readStatus;
} CProtocol;

/*
#define ssize_t long
#define size_t unsigned long
*/

//should be called from module_init
void initCProtocol(void);

/**
 * Update value in hardware based on pins
 */
void commitProtocol(CProtocol* p);

/**
 * Update out value based on hardware.
 * out->data should be from pin 1, 2, and 3
 */
void readProtocol(CProtocol* out);

/**
 * Update out value based on hardware.
 * out->data should be from pin 1 and 2
 * out->customData should be from pin 3
 */
void readProtocolWithCustomData(CProtocol* out);

//getters and setters to modify bits
/**
 * a byte consists of 8 bits
 * return bit 1, 2, 3 (I don't care LSB or MSB, doesn't matter) as byte
 * ex : byte from = 11100011b
 * returned : 00000111b (as byte)
 */
byte get1stThreeBit(byte from);

/**
 * a byte consists of 8 bits
 * return bit 4, 5, 6 (I don't care LSB or MSB, doesn't matter) as byte
 * ex : byte from = 11100011b
 * returned : 00000000b (as byte)
 */
byte get2ndThreeBit(byte from);

/**
 * a byte consists of 8 bits
 * return bit 7, 8 (I don't care LSB or MSB, doesn't matter) as byte
 * ex : byte from = 11100011b
 * returned : 00000011b (as byte)
 */
byte getLastTwoBit(byte from);

/**
 * a byte consists of 8 bits
 * set bit 1, 2, 3 (I don't care LSB or MSB, doesn't matter) of from to val
 * ex : set1stThreeBit(00000000b, 00000111b)
 * -> 11100000b
 */
void set1stThreeBit(byte* from, byte val);

/**
 * a byte consists of 8 bits
 * set bit 4, 5, 6 (I don't care LSB or MSB, doesn't matter) of from to val
 * ex : set2ndThreeBit(00000000b, 00000111b)
 * -> 00011100b
 */
void set2ndThreeBit(byte* from, byte val);

/**
 * a byte consists of 8 bits
 * set bit 7, 8 (I don't care LSB or MSB, doesn't matter) of from to val
 * ex : setLastTwoBit(00000000b, 00000011b)
 * -> 00000011b
 */
void setLastTwoBit(byte* from, byte val);

/**
 * read a byte from hardware, put the byteacter to out, and customData from hardware to outCustomData
 * return 3 if reading succeed
 */
int readAChar(byte* out, byte* outCustomData);

/**
 * write a byte to hardware
 * return 3 if writing succeed
 */
int writeAChar(byte in, byte customData);

/**
 * read characters from hardware until len or end of stream, put the characters to out
 * return the number of characters read
 */
ssize_t readABunch(byte* out, byte* foundEOT, size_t len);


/**
 * write characters to hardware as many as len
 * return the number of characters written
 */
ssize_t writeABunch(byte* in, size_t len);
